/*
    Copyright (c);2019-2022;Wiscom System;

	All rights reserved.

    Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. Neither the name of the Wiscom System nor the names of its contributors
       may be used to endorse or promote products derived from this software without
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/

#include "los_typedef.h"
#include "los_hwi.h"
#include "crc.h"
#include "pcrambox.h"
#include "los_task.h"
#include "string.h"

/**
 * TLSF include
 */
#include "los_compiler.h"
#include "los_hwi.h"
#include "los_task.ph"
#include "los_printf.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */ 

/**
 * The address of the static memory pool must be aligned to the boundary of 4.
 */
#define OS_BOXMEM_BASE_ALIGN  4
#define BOXMEM_ALIGN(value, alignSize)  ((UINT32)(value) | ((UINT32)(alignSize - 1))) + 1

/**
 * Get the address of the next memory node in the static memory pool.
 */
#define OS_pcrambox_NODE_NEXT(addr, uwBlkSize)  (VOID *)((UINT32)(addr) + (uwBlkSize))

/**
 * The magic word of the memory box.
 */
#define pcrambox_magicsize              4
#ifdef LOS_pcrambox_MAGIC_CHECK
#define OS_pcrambox_MAGIC              0xFFAAFFAA
#define OS_pcrambox_SET_MAGIC(addr)    *((UINT32 *)(addr)) = OS_pcrambox_MAGIC
#define OS_pcrambox_CHECK_MAGIC(addr)  ((*((UINT32 *)(addr)) == OS_pcrambox_MAGIC) ? LOS_OK: LOS_NOK)
#else
#define OS_pcrambox_SET_MAGIC(addr)
#define OS_pcrambox_CHECK_MAGIC(addr)  LOS_OK
#endif

/**
 * Get the address of memory block according to the magic word information.
 */
#define pcram_alloc_mempool_addr(addr)        (VOID *)((UINT32)addr + (UINT32)(2 * g_TVCBSize * g_TVCBNum) + pcrambox_magicsize + sizeof(LOS_MEM_POOL_INFO))
#define pcram_mempool_addr(addr)              (VOID *)((UINT32)addr + (UINT32)(2 * g_TVCBNum * g_TVCBSize) + pcrambox_magicsize)
#define OS_SCLIST_VIB_ADDR(addr)     ((VIB *)((UINT32)addr + SCLIST_TVCB_STRUCT_SIZE))
#define OS_pcrambox_USER_ADDR(addr)  ((VOID *)((UINT32 *)(addr) + LOS_pcrambox_MAGIC_SIZE))
#define OS_pcrambox_NODE_ADDR(addr)  (VOID *)(((UINT32 *)(addr) - LOS_pcrambox_MAGIC_SIZE))
#define OS_ADDR16to32(addr)          ((UINT32)((addr.HI16) << 16) | (UINT32)(addr.LO16))
//#define TIDEqual(TI1, TI2)            (((TI1.TID != TI2.TID)||(TI1.Identifier != TI2.Identifier)) ? LOS_NOK : LOS_OK)
#define TVCBOverflow(addr)           (((UINT32)g_TVBHead + g_TVCBSize * g_TVCBNum) < (UINT32)addr ? LOS_NOK : LOS_OK)
// #define isnotEmpty(addr)            (addr.HI16 != 0 && addr.LO16 != 0)
////SCYHF
#define isnotEmpty(addr)            (addr== 0)
////SCYHF
VOID *g_TVBHead = NULL;
UINT16 g_TVCBSize;                       //閸掓繂顫愰崠鏍櫡鏉╂稖顢戠挧瀣拷鍏兼惙娴ｏ拷
UINT16 g_VIBSize;                       //鐠囪鍟撻惃鍕閸婃瑨娴嗛幋锟�8娴ｅ秵瀚剧挧閿嬫降
UINT16 g_TVCBNum;

/**
 * TLSF define
 */
extern ST_LOS_TASK g_stLosTask;

#define AARCHPTR UINT32

LITE_OS_SEC_ALW_INLINE static inline INT32 __log2(UINT32 uwWord)
{
    return uwWord ? (sizeof(uwWord) * 8 - CLZ(uwWord) - 1) : 0;
}

LITE_OS_SEC_TEXT static inline INT32 tlsf_ffs(UINT32 uwWord)
{
    return __log2(uwWord & (UINT32)(-(UINT32)uwWord)); /*lint !e501*/
}

LITE_OS_SEC_TEXT static inline INT32 tlsf_fls(UINT32 uwWord)
{
    const INT32 swBit = uwWord ? 32 - CLZ(uwWord) : 0;
    return swBit - 1;
}

#define tlsf_fls_sizet tlsf_fls

/*
 * Block header structure.
 *
 * There are several implementation subtleties involved:
 * - The prev_phys_block field is only valid if the previous pNode is free.
 * - The prev_phys_block field is actually stored at the end of the
 *   previous pNode. It appears at the beginning of this structure only to
 *   simplify the implementation.
 * - The pNext_free / pPrev_free fields are only valid if the pNode is free.
 */
typedef struct LOS_MEM_DYN_NODE {
    /* Points to the previous physical pNode. */
    struct LOS_MEM_DYN_NODE *pstPreNode;
    /* The size of this pNode, excluding the pNode header. */
    UINT32 uwSize;
    /* Next and previous free blocks. */
    struct LOS_MEM_DYN_NODE *pNext_free;
    struct LOS_MEM_DYN_NODE *pPrev_free;
} LOS_MEM_DYN_NODE;

enum tlsf_public {
    SL_INDEX_COUNT_LOG2 = 2,
};

enum tlsf_private {
    /* All allocation sizes and addresses are aligned to 4 bytes. */
    ALIGN_SIZE_LOG2 = 2,
    ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
    FL_INDEX_MAX = 30,
    SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
    FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
    FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
    SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
};

typedef struct LOS_MEM_POOL_INFO {
    LOS_MEM_DYN_NODE stBlock_null;
    UINT32 uwPoolSize;
    UINT32 fl_bitmap;
    UINT32 sl_bitmap[FL_INDEX_COUNT];
    LOS_MEM_DYN_NODE *pstBlocks[FL_INDEX_COUNT][SL_INDEX_COUNT];


    UINT32 uwTlsf_AllocCount;
    UINT32 uwTlsf_FreeCount;
} LOS_MEM_POOL_INFO;

/* pool_t: a pNode of memory that TLSF can manage. */
typedef VOID *pool_t;

/* Add/remove memory pools. */
pool_t osMemPoolAdd(VOID *tlsf, VOID *pPool, UINT32 uwBytes);

/* Overheads/limits of internal structures. */
UINT32 osMemHeadSize(VOID);

/* Debugging. */
#define TSLF_CONFIG_DEBUG

#ifdef TLSF_CONFIG_ASSERT
#include <assert.h>
#define tlsf_assert(expr) assert(expr)
#define   alignCheck(align)  tlsf_assert(0 == ((align) & ((align) - 1)) && "must align to a power of two");
#else
#define tlsf_assert(expr) (VOID)(0)
#define   alignCheck(align)
#endif

/*
 * Cast and min/max macros.
 */
#define tlsf_cast(t, exp) ((t)(exp))
#define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
#define tlsf_max(a, b) ((a) > (b) ? (a) : (b))

#define tlsf_offset(a,b) LOS_OFF_SET_OF(a, b)



/*
 * Since pNode sizes are always at least a multiple of 4, the two least
 * significant bits of the size field are used to store the pNode status:
 * - bit 0: whether pNode is busy or free
 * - bit 1: whether previous pNode is busy or free
 */
static const UINT32 block_header_free_bit = 1 << 0;
static const UINT32 block_header_prev_free_bit = 1 << 1;

#define DEBUG_SPACE   4
////SCYHF
void *SCmemcpy(void *destin, void *source, unsigned n)
{
	uint8_t Tempsource[32]={0};
    if((source>0xE0000000)&&(source<0xE0800000))
    {
        EXMC_PCRAM_BufferRead(Tempsource,source,n);
    }
    else
    {
        memcpy(Tempsource,source,n);
    }
    if((destin>0xE0000000)&&(destin<0xE0800000))
    {
        EXMC_PCRAM_BufferWrite(Tempsource, destin, n);
    }
    else
    {
        memcpy(destin,Tempsource,n);
    }
}
/*
 * The size of the pNode header exposed to used blocks is the size field.
 * The pstPreNode field is stored *inside* the previous free pNode.
 */
static const UINT32 block_header_overhead = tlsf_offset(LOS_MEM_DYN_NODE, uwSize);

/* User data starts directly after the size field in a used pNode. */
static const UINT32 block_start_offset =
    tlsf_offset(LOS_MEM_DYN_NODE, uwSize) + sizeof(UINT32) + DEBUG_SPACE; /*lint !e413*/

/*
 * A free pNode must be large enough to store its header minus the size of
 * the pstPreNode field, and no larger than the number of addressable
 * bits for FL_INDEX.
 */
static const UINT32 block_size_min =
    sizeof(LOS_MEM_DYN_NODE) - sizeof(LOS_MEM_DYN_NODE *);
static const UINT32 block_size_max = tlsf_cast(UINT32, 1) << FL_INDEX_MAX;

#define control_t LOS_MEM_POOL_INFO

#define OS_MEM_TASKID_SET(node, ID)  \
            do \
            { \
                AARCHPTR uwTmp = (AARCHPTR)(((LOS_MEM_DYN_NODE *)node)->pNext_free); \
                uwTmp &= 0xffff0000; \
                uwTmp |= ID; \
                ((LOS_MEM_DYN_NODE *)node)->pNext_free = (LOS_MEM_DYN_NODE *)uwTmp; \
            }while(0)

#define OS_MEM_TASKID_GET(node)  ((AARCHPTR)(((LOS_MEM_DYN_NODE *)node)->pNext_free) & 0xffff)

VOID osMemInfoPrint(pool_t pPool);
#define IS_ALIGNED(value, alignSize)  (0 == (((AARCHPTR)(value)) & ((AARCHPTR)(alignSize - 1))))
/*
 * LOS_MEM_DYN_NODE member functions.
 */
LITE_OS_SEC_TEXT static VOID osMemNodeSizeSet(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    pNode->uwSize = uwSize | (pNode->uwSize & (block_header_free_bit | block_header_prev_free_bit));
}

LITE_OS_SEC_TEXT static UINT32 osMemNodeSizeGet(const LOS_MEM_DYN_NODE *pNode)
{
    return pNode->uwSize & ~(block_header_free_bit | block_header_prev_free_bit);
}

LITE_OS_SEC_TEXT static INT32 osMemEndCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return osMemNodeSizeGet(pNode) == 0;
}

LITE_OS_SEC_TEXT static INT32 os_MemFreeCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return tlsf_cast(INT32, pNode->uwSize & block_header_free_bit);
}

LITE_OS_SEC_TEXT static VOID osMemFreeMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize |= block_header_free_bit;
}

LITE_OS_SEC_TEXT static VOID osMemUsedMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize &= ~block_header_free_bit;
}

LITE_OS_SEC_TEXT static INT32 osMemPreFreeCheck(const LOS_MEM_DYN_NODE *pNode)
{
    return tlsf_cast(INT32, pNode->uwSize & block_header_prev_free_bit);
}

LITE_OS_SEC_TEXT static VOID osMemPreFreeMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize |= block_header_prev_free_bit;
}

LITE_OS_SEC_TEXT static VOID osMemPreUsedMark(LOS_MEM_DYN_NODE *pNode)
{
    pNode->uwSize &= ~block_header_prev_free_bit;
}

LITE_OS_SEC_TEXT LOS_MEM_DYN_NODE *osMemPtrToNode(const VOID *pPtr)
{
    // return tlsf_cast(LOS_MEM_DYN_NODE *,
    //                  tlsf_cast(UINT8*, pPtr) - block_start_offset);
    ////SCYHF
    return tlsf_cast(LOS_MEM_DYN_NODE *,
                     tlsf_cast(UINT8*, pPtr) - block_start_offset);
}

LITE_OS_SEC_TEXT static VOID *osMemNodeToPtr(const LOS_MEM_DYN_NODE *pNode)
{
    // return tlsf_cast(VOID *,
    //                  tlsf_cast(UINT8 *, pNode) + block_start_offset);
    ////SCYHF
    return tlsf_cast(VOID *,
                     tlsf_cast(UINT8 *, pNode) + block_start_offset);
}

/* Return location of next pNode after pNode of given size. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemPtrOffset(const VOID *pPtr, INT32 swSize)
{
    return tlsf_cast(LOS_MEM_DYN_NODE *, tlsf_cast(AARCHPTR, pPtr) + swSize);
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE * osMemFirstNode(VOID *pPool)
{
    return osMemPtrOffset((const VOID *)((AARCHPTR)pPool + osMemHeadSize()), -(INT32)block_header_overhead); /*lint !e570*/
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemEndNode(pool_t pPool)
{
    return (LOS_MEM_DYN_NODE *)((AARCHPTR)pPool + ((control_t *)pPool)->uwPoolSize - block_start_offset);
}

LITE_OS_SEC_TEXT static AARCHPTR osMemEndPtr(pool_t pPool)
{
    return (AARCHPTR)pPool + ((control_t *)pPool)->uwPoolSize;
}

/* Return location of previous pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodePre(const LOS_MEM_DYN_NODE *pNode)
{
    tlsf_assert(osMemPreFreeCheck(pNode) && "previous pNode must be free");
    return pNode->pstPreNode;
}

/* Return location of next existing pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeNext(const LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemPtrOffset(
        tlsf_cast(VOID *, pNode), (INT32)osMemNodeSizeGet(pNode));
    tlsf_assert(!osMemEndCheck(pNode));
    return pNext;
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNextLink(LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    pNext->pstPreNode = pNode;
    return pNext;
}

LITE_OS_SEC_TEXT static VOID osMemFreeSet(LOS_MEM_DYN_NODE *pNode)
{
    /* Link the pNode to the next pNode, first. */
    LOS_MEM_DYN_NODE *pNext = osMemNextLink(pNode);
    osMemPreFreeMark(pNext);
    osMemFreeMark(pNode);
}

LITE_OS_SEC_TEXT static VOID osMemUsedSet(LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    osMemPreUsedMark(pNext);
    osMemUsedMark(pNode);
}

LITE_OS_SEC_TEXT static AARCHPTR osMemAlignDown(AARCHPTR uwData, UINT32 uwAlign)
{
    alignCheck(uwAlign);
    return uwData - (uwData & (uwAlign - 1));
}

LITE_OS_SEC_TEXT static AARCHPTR osMemAlignUp(AARCHPTR uwData, UINT32 uwAlign)
{
    alignCheck(uwAlign);
    return (uwData + (AARCHPTR)(uwAlign - 1)) & ~((AARCHPTR)(uwAlign - 1));
}

LITE_OS_SEC_TEXT static VOID *osMemAlignPtr(const VOID *pPtr, UINT32 uwAlign)
{
    const AARCHPTR uwAligned = (tlsf_cast(AARCHPTR, pPtr) + (AARCHPTR)(uwAlign - 1)) & ~((AARCHPTR)(uwAlign - 1));
    alignCheck(uwAlign);
    return tlsf_cast(VOID *, uwAligned);
}

LITE_OS_SEC_TEXT static UINT32 osMemReqSizeAdjust(UINT32 uwSize, UINT32 uwAlign)
{
    UINT32 uwAdjust = 0;
    if (uwSize && uwSize < block_size_max)
    {
        const UINT32 uwAligned = osMemAlignUp(uwSize, uwAlign) + block_start_offset;
        uwAdjust = tlsf_max(uwAligned, block_size_min);
    }
    return uwAdjust;
}

LITE_OS_SEC_TEXT static VOID osMemMapInsert(UINT32 uwSize, INT32 *pFli, INT32 *pSli)
{
    INT32 swFl, swSl;
    if (uwSize < SMALL_BLOCK_SIZE)
    {
        /* Store small blocks in first list. */
        swFl = 0;
        swSl = tlsf_cast(INT32, uwSize) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
    }
    else
    {
        swFl = tlsf_fls_sizet(uwSize);
        swSl = tlsf_cast(INT32, uwSize >> (swFl - SL_INDEX_COUNT_LOG2)) ^
             (1 << SL_INDEX_COUNT_LOG2);
        swFl -= (FL_INDEX_SHIFT - 1);
    }

    *pFli = swFl;
    *pSli = swSl;
    //PRINT_ERR("FL = %d, SL = %d\n", swFl,swSl);
}

LITE_OS_SEC_TEXT static VOID osMemMapSearch(UINT32 uwSize, INT32 *pFli, INT32 *pSli)
{
    if (uwSize >= SMALL_BLOCK_SIZE) {
        const UINT32 uwRound = (1 << (tlsf_fls_sizet(uwSize) - SL_INDEX_COUNT_LOG2)) - 1;
        uwSize += uwRound;
    }
    osMemMapInsert(uwSize, pFli, pSli);
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemSuitableNodeSearch(control_t *control,
                                             INT32 *pFli, INT32 *pSli)
{
    INT32 swFl = *pFli;
    INT32 swSl = *pSli;
    UINT32 swSl_map = control->sl_bitmap[swFl] & (((UINT32)~0) << swSl);
    if (!swSl_map) {
        
        /* No pNode exists. Search in the next largest first-level list. */
        const UINT32 swFl_map = control->fl_bitmap & (((UINT32)~0) << (swFl + 1));
        if (!swFl_map) {
            /* No free blocks available, memory has been exhausted. */
        	printf("No free blocks available, memory has been exhausted. \r\n");
            return NULL;
        }

        swFl = tlsf_ffs(swFl_map);
        *pFli = swFl;
        swSl_map = control->sl_bitmap[swFl];
    }
    tlsf_assert(swSl_map && "internal error - second level bitmap is null");
    swSl = tlsf_ffs(swSl_map);
    *pSli = swSl;

    /* Return the first pNode in the free list. */
    return control->pstBlocks[swFl][swSl];
}

LITE_OS_SEC_TEXT static VOID osMemFreeNodeRemove(control_t *control,
                              LOS_MEM_DYN_NODE *pNode,
                              INT32 swFl, INT32 swSl)
{
    LOS_MEM_DYN_NODE *pPrev = pNode->pPrev_free;
    LOS_MEM_DYN_NODE *pNext = pNode->pNext_free;
    tlsf_assert(pPrev && "pPrev_free field can not be null");
    tlsf_assert(pNext && "pNext_free field can not be null");
    pNext->pPrev_free = pPrev;
    pPrev->pNext_free = pNext;
    /* If this pNode is the head of the free list, set new head. */
    if (control->pstBlocks[swFl][swSl] == pNode) {
        control->pstBlocks[swFl][swSl] = pNext;
        /* If the new head is null, clear the bitmap. */
        if (pNext == &control->stBlock_null) {
            control->sl_bitmap[swFl] &= ~(1 << swSl); /*lint !e502*/

            /* If the second bitmap is now empty, clear the fl bitmap. */
            if (!control->sl_bitmap[swFl]) {
                control->fl_bitmap &= ~(1 << swFl); /*lint !e502*/
            }
        }
    }
}

/* Insert a free pNode into the free pNode list. */
LITE_OS_SEC_TEXT static VOID osMemFreeNodeInsert(control_t *control,
                              LOS_MEM_DYN_NODE *pNode,
                              INT32 swFl, INT32 swSl)
{
    LOS_MEM_DYN_NODE *pstCurrent = control->pstBlocks[swFl][swSl];
    //tlsf_assert(pstCurrent && "free list cannot have a null entry");
    //tlsf_assert(pNode && "cannot insert a null entry into the free list");
    pNode->pNext_free = pstCurrent;
    pNode->pPrev_free = &control->stBlock_null;
    pstCurrent->pPrev_free = pNode;
    tlsf_assert(osMemNodeToPtr(pNode) ==
                    osMemAlignPtr(osMemNodeToPtr(pNode), ALIGN_SIZE) &&
                "pNode not aligned properly");
    /*
     * Insert the new pNode at the head of the list, and mark the first-
     * and second-level bitmaps appropriately.
     */
    control->pstBlocks[swFl][swSl] = pNode;
    control->fl_bitmap |= (1 << swFl);
    control->sl_bitmap[swFl] |= (1 << swSl);
}

/* Remove a given pNode from the free list. */
LITE_OS_SEC_TEXT static VOID osMemNodeRemove(control_t *control, LOS_MEM_DYN_NODE *pNode)
{
    INT32 swFl, swSl;
    osMemMapInsert(osMemNodeSizeGet(pNode), &swFl, &swSl);
    osMemFreeNodeRemove(control, pNode, swFl, swSl);
}

/* Insert a given pNode into the free list. */
LITE_OS_SEC_TEXT static VOID osMemNodeInsert(control_t *control, LOS_MEM_DYN_NODE *pNode)
{
    INT32 swFl, swSl;
    osMemMapInsert(osMemNodeSizeGet(pNode), &swFl, &swSl);
    osMemFreeNodeInsert(control, pNode, swFl, swSl);
}

LITE_OS_SEC_TEXT static INT32 osMemNodeSpitCheck(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    return osMemNodeSizeGet(pNode) >= sizeof(LOS_MEM_DYN_NODE) + uwSize;
}

/* Split a pNode into two, the second of which is free. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeSpit(LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    /* Calculate the amount of space left in the remaining pNode. */
    LOS_MEM_DYN_NODE *remaining = osMemPtrOffset((VOID *)pNode, (INT32)uwSize);

    const UINT32 remain_size = osMemNodeSizeGet(pNode) - (uwSize);

    tlsf_assert(osMemNodeToPtr(remaining) == osMemAlignPtr(osMemNodeToPtr(remaining),
                                                     ALIGN_SIZE) &&
                "remaining pNode not aligned properly");

    tlsf_assert(osMemNodeSizeGet(pNode) ==
                remain_size + uwSize);
    osMemNodeSizeSet(remaining, remain_size);
    tlsf_assert(osMemNodeSizeGet(remaining) >= block_size_min &&
                "pNode split with invalid size");

    osMemNodeSizeSet(pNode, uwSize);
    osMemFreeSet(remaining);

    return remaining;
}

/* Absorb a free pNode's storage into an adjacent previous free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNodeAbsorb(LOS_MEM_DYN_NODE *pPrev, LOS_MEM_DYN_NODE *pNode)
{
    tlsf_assert(!osMemEndCheck(pPrev) && "previous pNode can't be last");
    /* Note: Leaves flags untouched. */
    pPrev->uwSize += osMemNodeSizeGet(pNode);
    (VOID)osMemNextLink(pPrev);
    return pPrev;
}

/* Merge a just-freed pNode with an adjacent previous free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemPreNodeMerge(control_t *control,
                                        LOS_MEM_DYN_NODE *pNode)
{
    if (osMemPreFreeCheck(pNode)) {
        LOS_MEM_DYN_NODE *pPrev = osMemNodePre(pNode);
        tlsf_assert(pPrev && "prev physical pNode can't be null");
        tlsf_assert(os_MemFreeCheck(pPrev) &&
                    "prev pNode is not free though marked as such");
        osMemNodeRemove(control, pPrev);
        pNode = osMemNodeAbsorb(pPrev, pNode);
    }

    return pNode;
}

/* Merge a just-freed pNode with an adjacent free pNode. */
LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemNextNodeMerge(control_t *control,
                                        LOS_MEM_DYN_NODE *pNode)
{
    LOS_MEM_DYN_NODE *pNext = osMemNodeNext(pNode);
    tlsf_assert(pNext && "next physical pNode can't be null");

    if (os_MemFreeCheck(pNext)) {
        tlsf_assert(!osMemEndCheck(pNode) && "previous pNode can't be last");
        osMemNodeRemove(control, pNext);
        pNode = osMemNodeAbsorb(pNode, pNext);
    }

    return pNode;
}

/* Trim any trailing pNode space off the end of a pNode, return to pool. */
LITE_OS_SEC_TEXT static VOID osMemFreeNodeTrim(control_t *control,
                            LOS_MEM_DYN_NODE *pNode,
                            UINT32 uwSize)
{
    tlsf_assert(os_MemFreeCheck(pNode) && "pNode must be free");
    if (osMemNodeSpitCheck(pNode, uwSize))
    {
        LOS_MEM_DYN_NODE *remaining_block = osMemNodeSpit(pNode, uwSize);
        (VOID)osMemNextLink(pNode);
        osMemPreFreeMark(remaining_block);
        osMemNodeInsert(control, remaining_block);
    }
}

/* Trim any trailing pNode space off the end of a used pNode, return to pool. */
LITE_OS_SEC_TEXT_MINOR static VOID osMemUsedNodeTrim(control_t *control,
                            LOS_MEM_DYN_NODE *pNode,
                            UINT32 uwSize)
{
    tlsf_assert(!os_MemFreeCheck(pNode) && "pNode must be used");
    if (osMemNodeSpitCheck(pNode, uwSize)) {
        /* If the next pNode is free, we must coalesce. */
        LOS_MEM_DYN_NODE *remaining_block = osMemNodeSpit(pNode, uwSize);
        osMemPreUsedMark(remaining_block);
        remaining_block->pstPreNode = pNode;

        remaining_block = osMemNextNodeMerge(control, remaining_block);
        osMemNodeInsert(control, remaining_block);
    }
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemFreeNodeTrimLeading(control_t *control,
                                               LOS_MEM_DYN_NODE *pNode,
                                               UINT32 uwSize)
{
    LOS_MEM_DYN_NODE *remaining_block = pNode;
    if (osMemNodeSpitCheck(pNode, uwSize)) {
        /* We want the 2nd pNode. */
        remaining_block = osMemNodeSpit(pNode, uwSize);
        osMemPreFreeMark(remaining_block);

        (VOID)osMemNextLink(pNode);
        osMemNodeInsert(control, pNode);
    }

    return remaining_block;
}

LITE_OS_SEC_TEXT static LOS_MEM_DYN_NODE *osMemFreeNodeLocate(control_t *control, UINT32 uwSize)
{
    INT32 swFl = 0, swSl = 0;
    LOS_MEM_DYN_NODE *pNode = NULL;

    if (uwSize) {
        osMemMapInsert(uwSize, &swFl, &swSl);
        pNode = osMemSuitableNodeSearch(control, &swFl, &swSl);
    }

    if (pNode) {
        if (osMemNodeSizeGet(pNode) >= uwSize)
            goto EXIT;
        while (pNode->pNext_free != &control->stBlock_null)
        {
            pNode = pNode->pNext_free;
            if (osMemNodeSizeGet(pNode) >= uwSize)
                goto EXIT;
        }
        osMemMapSearch(uwSize, &swFl, &swSl);
        pNode = osMemSuitableNodeSearch(control, &swFl, &swSl);
        if (pNode == NULL || osMemNodeSizeGet(pNode) < uwSize)
            return NULL;
EXIT:
        osMemFreeNodeRemove(control, pNode, swFl, swSl);
    }

    if (pNode && !pNode->uwSize)
        pNode = NULL;

    return pNode;
}

LITE_OS_SEC_TEXT static VOID *osMemUsedNodePrepare(control_t *control, LOS_MEM_DYN_NODE *pNode, UINT32 uwSize)
{
    VOID *pPtr = NULL;
    
    if (pNode)
    {
        tlsf_assert(uwSize && "size must be non-zero");
        osMemFreeNodeTrim(control, pNode, uwSize);
        osMemUsedSet(pNode);



        /* If the operation occured before task initialization(g_stLosTask.pstRunTask was not assigned)
           or in interrupt,make the value of taskid of pNode to oxffffffff*/
        if (g_stLosTask.pstRunTask != NULL && OS_INT_INACTIVE)
        {
            OS_MEM_TASKID_SET(pNode, g_stLosTask.pstRunTask->uwTaskID);
        }
        else
        {
            /* If the task mode does not initialize, the field is the 0xffffffff */
            OS_MEM_TASKID_SET(pNode, OS_NULL_INT);
            /* TODO: the commend task-MEMUSE is not include system initialization malloc */
        }



        pPtr = osMemNodeToPtr(pNode);
    }
    else
    {
        PRINT_INFO("-----------------------------------------------------------------------------------------------------------\n");
        osMemInfoPrint((pool_t)control);
        PRINT_ERR("No suitable free block, require free node size: 0x%x\n", uwSize);
        PRINT_INFO("-----------------------------------------------------------------------------------------------------------\n");
        return NULL;
    }
    return pPtr;
}

/* Clear structure and point all empty lists at the null pNode. */
LITE_OS_SEC_TEXT_INIT static VOID osMemControlClear(control_t *control, UINT32 uwBytes)
{
    UINT32 uwFlIndex, uwSlIndex;

    control->stBlock_null.pNext_free = &control->stBlock_null;
    control->stBlock_null.pPrev_free = &control->stBlock_null;

    control->uwPoolSize = uwBytes;

    control->fl_bitmap = 0;
    for (uwFlIndex = 0; uwFlIndex < FL_INDEX_COUNT; ++uwFlIndex) {
        control->sl_bitmap[uwFlIndex] = 0;
        for (uwSlIndex = 0; uwSlIndex < SL_INDEX_COUNT; ++uwSlIndex) {
            control->pstBlocks[uwFlIndex][uwSlIndex] = &control->stBlock_null;
        }
    }
}

/*
 * Debugging utilities.
 */
#ifdef TSLF_CONFIG_DEBUG
LITE_OS_SEC_TEXT static UINT32 osMemNodeInsideCheck(pool_t pPool, VOID *pPtr)
{
    if (((AARCHPTR)pPtr < (AARCHPTR)osMemFirstNode(pPool))  ||
        ((AARCHPTR)pPtr > (AARCHPTR)osMemEndNode(pPool)))
        return LOS_NOK;
    else
        return LOS_OK;
}

LITE_OS_SEC_TEXT INT32 osMemMagicCheck(pool_t pPool, VOID *pPtr)
{
    const LOS_MEM_DYN_NODE *pNode = NULL;

    if(pPtr == NULL || !IS_ALIGNED(pPtr, sizeof(VOID *)))
    {
        return LOS_NOK;
    }
    else
    {
        pNode = osMemPtrToNode(pPtr);
    }

    if (pNode == osMemFirstNode(pPool))
        return LOS_OK;
    else if ((AARCHPTR)pNode->pstPreNode & (ALIGN_SIZE - 1))
        return LOS_NOK;
    else if(osMemNodeInsideCheck(pPool, pNode->pstPreNode) == LOS_NOK)
        return LOS_NOK;
    else if ((AARCHPTR)pNode == (AARCHPTR)osMemNodeNext(pNode->pstPreNode))
        return LOS_OK;
    else
        return LOS_NOK;
}

LITE_OS_SEC_TEXT UINT32 osMemInfoGet(pool_t pPool, LOS_MEM_STATUS *pstStatus)
{
    LOS_MEM_DYN_NODE *pNode = osMemFirstNode(pPool);
    UINT32 uwTotalUsedSize = 0, uwTotalFreeSize = 0, uwMaxFreeNodeSize = 0;
    UINT32 uwTmpSize = 0;
    UINTPTR uvIntSave;
    control_t *control = tlsf_cast(control_t *, pPool);

    if (pstStatus == NULL)
    {
        return LOS_NOK;
    }

    if (pPool == NULL)
    {
        PRINT_ERR("wrong mem pool addr: 0x%x\n", (UINT32)pPool);
        return LOS_NOK;
    }

    if (osMemMagicCheck(pPool, (VOID *)osMemEndPtr(pPool)) == LOS_NOK)
    {
        PRINT_ERR("wrong mem pool addr: 0x%x\n", (UINT32)pPool);
        return LOS_NOK;
    }

    uvIntSave = LOS_IntLock();

    while (pNode && !osMemEndCheck(pNode)) {
        uwTmpSize = osMemNodeSizeGet(pNode);
        if (os_MemFreeCheck(pNode))
        {
            uwTotalFreeSize += uwTmpSize;
            if (uwTmpSize > uwMaxFreeNodeSize)
                uwMaxFreeNodeSize = uwTmpSize;
        }
        else
        {
            uwTotalUsedSize += uwTmpSize;
        }
        pNode = osMemNodeNext(pNode);
    }

    pstStatus->usedSize = uwTotalUsedSize + block_start_offset;
    pstStatus->freeSize = uwTotalFreeSize;
    pstStatus->totalSize = uwMaxFreeNodeSize;
    pstStatus->allocCount = control->uwTlsf_AllocCount;
    pstStatus->freeCount = control->uwTlsf_FreeCount;

    LOS_IntRestore(uvIntSave);

    return LOS_OK;

}

LITE_OS_SEC_TEXT VOID osMemInfoPrint(pool_t pPool)
{
    LOS_MEM_POOL_INFO *pstPoolInfo = (LOS_MEM_POOL_INFO *)pPool;
    LOS_MEM_STATUS stStatus = {0};
    if (LOS_NOK == osMemInfoGet(pPool, &stStatus))
        return;

    PRINT_ERR("pool addr    pool size    total size     used size    free size   alloc Count    free Count\n    0x%-8x   0x%-8x   0x%-8x    0x%-8x   0x%-16x   0x%-13x    0x%-13x\n",
                (UINT32)pPool, pstPoolInfo->uwPoolSize, stStatus.totalSize, stStatus.usedSize, stStatus.freeSize, stStatus.allocCount, stStatus.freeCount); /*lint !e515*/
    return;
}

LITE_OS_SEC_TEXT_INIT UINT32 osMemPoolSizeGet(VOID * tlsf)
{
    control_t *control = tlsf_cast(control_t *, tlsf);
    if (tlsf == NULL)
        return LOS_NOK;

    return control->uwPoolSize;
}
#endif /* TLSF_CONFIG_DEBUG */

LITE_OS_SEC_TEXT_INIT UINT32 osMemHeadSize(VOID)
{
    return sizeof(control_t);
}

LITE_OS_SEC_TEXT_INIT pool_t osMemPoolAdd(VOID *tlsf, VOID *pPool, UINT32 uwBytes)
{
    LOS_MEM_DYN_NODE *pNode;
    LOS_MEM_DYN_NODE *pNext;
    const UINT32 uwPoolBytes = osMemAlignDown(uwBytes - block_start_offset, ALIGN_SIZE) + block_header_overhead;

    if (((AARCHPTR)pPool % ALIGN_SIZE) != 0) {
        PRINT_ERR("Memory must be aligned by %u bytes.\n", (INT32)ALIGN_SIZE);
        return NULL;
    }
    if (uwPoolBytes < block_size_min || uwPoolBytes > block_size_max)
    {
        PRINT_ERR("Memory size must be between 0x%x and 0x%x bytes.\n",
               (INT32)(block_start_offset + block_size_min),
               (INT32)(block_start_offset + block_size_max));/*lint !e515*/

        return NULL;
    }
    /*
     * Create the main free pNode. Offset the start of the pNode slightly
     * so that the pstPreNode field falls outside of the pool -
     * it will never be used.
    */
    pNode = osMemPtrOffset(pPool, -(INT32)block_header_overhead); /*lint !e570*/
    osMemNodeSizeSet(pNode, uwPoolBytes);
    osMemFreeMark(pNode);
    osMemPreUsedMark(pNode);
    osMemNodeInsert(tlsf_cast(control_t *, tlsf), pNode);
    /* Split the pNode to create a zero-size sentinel pNode. */
    pNext = osMemNextLink(pNode);
    osMemNodeSizeSet(pNext, 0);
    osMemUsedMark(pNext);
    osMemPreFreeMark(pNext);

    return pPool;
}

/*
 * TLSF main interface.
 */

LITE_OS_SEC_TEXT_INIT VOID * osMemPoolCreat(VOID *pPool, UINT32 uwBytes)
{
    if (((AARCHPTR)pPool % ALIGN_SIZE) != 0)
    {
        PRINT_ERR("Memory must be aligned to %u bytes.\n", (UINT32)ALIGN_SIZE);
        return NULL;
    }

    osMemControlClear(tlsf_cast(control_t *, pPool), uwBytes);

    return tlsf_cast(VOID *, pPool);
}

/*****************************************************************************
 Function : OS_MemInit
 Description : Initialize Dynamic Memory pool
 Input       : pPool    --- Pointer to memory pool
               uwBytes  --- Size of memory in bytes to allocate
 Output      : None
 Return      : LOS_OK - Ok, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 OS_MemInit(VOID *pPool, UINT32 uwBytes)
{
    VOID *tlsf;
    UINTPTR uvIntSave;
    if (!pPool || uwBytes <= osMemHeadSize())
    {
        return LOS_NOK;
    }
    uvIntSave = LOS_IntLock();
    if(!IS_ALIGNED(uwBytes, ALIGN_SIZE))
    {
        PRINT_ERR("pool [0x%x, 0x%x) size 0x%x sholud be aligned with ALIGN_SIZE\n",
                  (UINT32)pPool, (AARCHPTR)pPool + uwBytes, uwBytes);/*lint !e515*/
        uwBytes = osMemAlignDown(uwBytes, ALIGN_SIZE);
    }

    tlsf = osMemPoolCreat(pPool, uwBytes);
    if (osMemPoolAdd(tlsf, (UINT8 *)pPool + osMemHeadSize(), uwBytes - osMemHeadSize()) == 0)
    {
        LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    LOS_IntRestore(uvIntSave);
    return LOS_OK;
}



LITE_OS_SEC_TEXT VOID *os_HeapAlloc(VOID *tlsf, UINT32 uwSize)
{
    UINT32 adjust;
    LOS_MEM_DYN_NODE *pNode;
    VOID *pPtr = NULL;
    control_t *control = tlsf_cast(control_t *, tlsf);

    adjust = osMemReqSizeAdjust(uwSize, ALIGN_SIZE);
    if(0 == adjust)
    {
        PRINT_ERR("require node size 0x%x is too large\n",uwSize);
        return NULL;
    }
    printf("control,adjust is %p,%p\r\n",(UINT32)tlsf,(UINT32)adjust);
    pNode = osMemFreeNodeLocate(control, adjust);
    pPtr = osMemUsedNodePrepare(control, pNode, adjust);

    if (NULL != pPtr)
    {
        control->uwTlsf_AllocCount++;
    }

    return pPtr;
}

/*****************************************************************************
 Function : LOS_MemAlloc
 Description : Allocate Memory from Memory pool
 Input       : tlsf    --- Pointer to memory pool
               uwSize  --- Size of memory in bytes to allocate
 Output      : None
 Return      : Pointer to allocated memory
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *OS_MemAlloc(VOID * tlsf, UINT32 uwSize)
{
    VOID *pPtr = NULL;
    UINTPTR uvIntSave;

    if ((0 == uwSize) || (NULL == tlsf) || (uwSize > block_size_max))
    {
        return NULL;
    }
    uvIntSave = LOS_IntLock();

    {
        pPtr = os_HeapAlloc(tlsf, uwSize);
    }
    LOS_IntRestore(uvIntSave);
    return pPtr;
}


LITE_OS_SEC_TEXT BOOL os_HeapFree(VOID * tlsf, VOID *pPtr)
{
    control_t *control;

    LOS_MEM_DYN_NODE *pNode;

    control = (LOS_MEM_POOL_INFO *)tlsf;
    pNode = osMemPtrToNode(pPtr);

    if (os_MemFreeCheck(pNode))
    {
        return FALSE;
    }

    if (osMemMagicCheck(tlsf, pPtr) == LOS_NOK)
    {
        return FALSE;
    }

    osMemFreeSet(pNode);
    pNode = osMemPreNodeMerge(control, pNode);
    pNode = osMemNextNodeMerge(control, pNode);
    osMemNodeInsert(control, pNode);

    control->uwTlsf_FreeCount++;

    return TRUE;
}

/*****************************************************************************
 Function : LOS_MemFree
 Description : Free Memory and return it to Memory pool
 Input       : tlsf     --- Pointer to memory pool
               pPtr     --- Pointer to memory to free
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 OS_MemFree(VOID * tlsf, VOID *pPtr)
{
    UINTPTR uvIntSave;
    BOOL uwRet;


    if ((NULL == tlsf) || (NULL == pPtr))
    {
        return LOS_NOK;
    }
    uvIntSave = LOS_IntLock();
 
            uwRet = os_HeapFree(tlsf,pPtr);

    LOS_IntRestore(uvIntSave);
    return (uwRet == TRUE ? LOS_OK : LOS_NOK);
}



LITE_OS_SEC_TEXT UINT32 OS_MemStatisticsGet(VOID *pPool, LOS_MEM_STATUS *pstStatus)
{
    LOS_MEM_POOL_INFO *pstPoolInfo = (LOS_MEM_POOL_INFO *)pPool;
    LOS_MEM_STATUS stStatus;
    if (LOS_NOK == osMemInfoGet(pPool, &stStatus))
    {
        return LOS_NOK;
    }

    pstStatus->totalSize  = stStatus.totalSize;
    pstStatus->usedSize   = stStatus.usedSize;
    pstStatus->freeSize   = stStatus.freeSize;
    pstStatus->allocCount = stStatus.allocCount;
    pstStatus->freeCount  = stStatus.freeCount;

    return LOS_OK;
}

/**
 * sclist main function
 */
 ////SCYHF
LITE_OS_SEC_TEXT UINT32 TIDEqual(TIdentifier TI1, TIdentifier TI2)
{
    uint32_t TempT1_TID,TempT2_TID;
    uint8_t TempT1_Identifier[8]={0};
    uint8_t TempT2_Identifier[8]={0};
    TempT1_TID=TI1.TID;
    TempT2_TID=TI2.TID;
    if((TI1.Identifier>0xE0000000)&&(TI1.Identifier<0xE0800000))
    {
        EXMC_PCRAM_BufferRead(TempT1_Identifier,TI1.Identifier,8);
    }
    else
    {
        memcpy(TempT1_Identifier,TI1.Identifier,8);
    }
    if((TI2.Identifier>0xE0000000)&&(TI2.Identifier<0xE0800000))
    {
        EXMC_PCRAM_BufferRead(TempT2_Identifier,TI2.Identifier,8);
    }
    else
    {
        memcpy(TempT2_Identifier,TI2.Identifier,8);
    }
    if(TempT1_TID != TempT2_TID)
    {
        return LOS_NOK;
    }
    UINT16 i = 0;
    while(TempT1_Identifier[i] != '\0' && TempT2_Identifier[i] != '\0')
    {
        if(TempT1_Identifier[i] != TempT2_Identifier[i])
        {
            return LOS_NOK;
        }
        i++;
    }
    if(TempT1_Identifier[i] != '\0' || TempT2_Identifier[i] != '\0')
    {
        return LOS_NOK;
    }
    return LOS_OK;


    // if(TI1.TID != TI2.TID)
    // {
    //     return LOS_NOK;
    // }
    // UINT16 i = 0;
    // while(TI1.Identifier[i] != '\0' && TI2.Identifier[i] != '\0')
    // {
    //     if(TI1.Identifier[i] != TI2.Identifier[i])
    //     {
    //         return LOS_NOK;
    //     }
    //     i++;
    // }
    // if(TI1.Identifier[i] != '\0' || TI2.Identifier[i] != '\0')
    // {
    //     return LOS_NOK;
    // }
    // return LOS_OK;
    
}

/*****************************************************************************
 Function : osFoundVIB
 Description : Found the target VIB
 Input       : TID, Identifier 
 Output      : None
 Return      : VIB  --- Pointer to the VIB
*****************************************************************************/
// LITE_OS_SEC_TEXT VOID *osFoundVIB(UINT8 TID, UINT8 Identifier[])
////SCYHF
LITE_OS_SEC_TEXT VOID *osFoundVIB(UINT32 TID, UINT8 Identifier[])
////SCYHF
{
    TVCB *curTVCB = (TVCB *)g_TVBHead;
    VIB *curVIB = NULL;
    TIdentifier curVar;
    UINT8 TVCBCount = 0;
    curVar.TID = TID;

    SCmemcpy(curVar.Identifier, Identifier, 8);//curVar.Identifier = Identifier;
    // ////SCYHF
    // EXMC_PCRAM_BufferWrite(Identifier,curVar.Identifier,8);
    // ////SCYHF
    while((curTVCB->varNum == 0) ||  (curTVCB->TID != TID))
    {
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
        if(TVCBOverflow(curTVCB) == LOS_NOK)
        {
            return NULL;
        }
    }
    if(curTVCB->TID == TID)
    {
 //       printf("the found TVCB  is %p\r\n",(curTVCB));
        curVIB = OS_SCLIST_VIB_ADDR(curTVCB);                        /*skip the length of the parameter varNum*/
        while(((TIDEqual(curVIB->varName, curVar)) == LOS_NOK) && (curVIB < curTVCB + g_TVCBSize))
        {
            curVIB ++;
        }
        if(TIDEqual(curVIB->varName, curVar) == LOS_OK)
        {
            printf("the found vib  is %p\r\n\n",(curVIB));
            // printf("the found vib addrstart is %p\r\n\n",OS_ADDR16to32(curVIB->addrStart));
            ////SCYHF
            printf("the found vib addrstart is %p\r\n\n",(curVIB->addrStart));
            ////SCYHF
            return (VOID *)curVIB;
        }
    }
    return NULL;
}

/*****************************************************************************
 Function : osCreateVIB
 Description : Create the target VIB
 Input       : *pRet, Identifier, BlkNum, 
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
// LITE_OS_SEC_TEXT UINT32 osCreateVIB(VOID *pRet, UINT8 curTID, UINT8 Identifier[], UINT16 BlkNum)
////SCYHF
LITE_OS_SEC_TEXT UINT32 osCreateVIB(VOID *pRet, UINT32 curTID, UINT8 Identifier[], UINT32 BlkNum)
{
    TVCB *curTVCB = (TVCB *)g_TVBHead;
//    printf("the begin tvcb is %p\r\n",curTVCB);
    VIB *curVIB = NULL;
    TIdentifier curVar;
    UINT8 TVCBCount = 0;
    VIB *curVIBBackup = NULL;
    curVar.TID = curTID;

    SCmemcpy(curVar.Identifier, Identifier, 8);
    // ////SCYHF
    // EXMC_PCRAM_BufferWrite(Identifier,curVar.Identifier,8);
    // ////SCYHF
    curVar.Identifier[7] = '\0';
    while(((curTVCB->TID != curTID) && (curTVCB->varNum != 0)) && (TVCBCount <= g_TVCBNum))
    {
 //       printf("curtvcb.tid,num =%d,%d\r\n",curTVCB->TID,curTVCB->varNum);
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
        TVCBCount++;
    }
 //   printf("the create tvcb is %p,tvcbcount = %d\r\n",curTVCB,TVCBCount);
    if(TVCBCount > g_TVCBNum)
    {
        return LOS_NOK;
    }
    curVIB = OS_SCLIST_VIB_ADDR(curTVCB); 
    if(curTVCB->varNum == 0)
    {
 //       printf("the varnum is %d\r\n",curTVCB->varNum);
        curTVCB->TID = curTID;
    }
    else
    {
 //       printf("the varnum is %d\r\n",curTVCB->varNum);
        if(curTVCB->varNum * g_VIBSize > g_TVCBSize)
        {
            
            return LOS_NOK;
        }
        UINT8 varCount = 1;
        while((TIDEqual(curVIB->varName, curVar) == LOS_NOK) && (isnotEmpty(curVIB->addrStart)))
        {
            curVIB ++;
            varCount++;
        }
    }
    // curVIB->addrStart.HI16 = (UINT16)(((UINT32)pRet & 0xFFFF0000)>>16);
    // curVIB->addrStart.LO16 = (UINT16)((UINT32)pRet & 0x0000FFFF);
    ////SCYHF
    curVIB->addrStart=pRet;
    ////SCYHF
    // printf("the create vib addrstart is %p\r\n",OS_ADDR16to32(curVIB->addrStart));
    // printf("the create vib  is %p\r\n",(UINT32)curVIB);
    curVIB->varBlkNum = BlkNum;
    curVIB->varName = curVar;
    // printf("the create vib name is %s\r\n",curVIB->varName.Identifier);
    curVIB->varCRC = calc_crc16(0, curVIB, 16);
    curTVCB->varNum++;
    curVIBBackup = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    SCmemcpy(curVIBBackup, curVIB, sizeof(VIB));
    return LOS_OK;
}

/*****************************************************************************
 Function : osDeleteVIB
 Description : Delete the target VIB
 Input       : *pRet
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osDeleteVIB(VOID *pRet)
{
    UINT32 uwRet = LOS_NOK;
    VIB *curVIB = (VIB *) pRet;
    VIB *BackupVIB;
    // curVIB->addrStart.HI16 = 0;
    // curVIB->addrStart.LO16 = 0;
    ////SCYHF
    curVIB->addrStart=0;
    ////SCYHF
    curVIB->varBlkNum = 0;
    curVIB->varCRC = 0;
    BackupVIB = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    SCmemcpy(BackupVIB, curVIB, sizeof(VIB));
   ((TVCB *)(curVIB->fromTVCB))->varNum --;
    return LOS_OK;
}

/*****************************************************************************
 Function : osCheckCRC
 Description : Check whether the CRC is valid
 Input       : VIB  --- Pointer to the VIB
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osCheckCRC(VOID *VIBInfo)
{
    UINT16 curCRC;
    curCRC = calc_crc16(0,VIBInfo, 16);
    if (((VIB *)VIBInfo)->varCRC == curCRC)
    {
        return LOS_OK;
    }
    else
    {
        return LOS_NOK;
    }
}

/*****************************************************************************
 Function : osRecoverSClist
 Description : recover sclist from sclist2
 Input       : sclist2  --- Pointer to the sclist2
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT VOID osRecoverSClist(VIB *curVIB)
{
    VIB *BackupVIB;
    BackupVIB = (VIB *)((UINT32)curVIB + (UINT32)g_TVCBSize * (UINT32)g_TVCBNum);
    SCmemcpy(curVIB, BackupVIB, sizeof(VIB));
}

/*****************************************************************************
 Function : osIndexInit
 Description : Init index area
 Input       : None
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 osIndexInit(VOID *TVCB_Head)
{
    TVCB *curTVCB = (TVCB *)TVCB_Head;
    VIB *curVIB = NULL;
    UINT32 TVBLength = g_TVCBNum * g_TVCBSize;
    ////SCYHF
    UINT32 TempData = 0;
    ////SCYHF
    while(curTVCB < (UINT32)TVCB_Head + TVBLength)
    {
        // curTVCB->TID = 0;
        // curTVCB->varNum = 0;
        ////SCYHF
        // (*((UINT32 *)curTVCB))=0;//TID AND varNum
        curTVCB->TID = 0;
        curTVCB->varNum = 0;
        ////SCYHF
        curVIB = OS_SCLIST_VIB_ADDR(curTVCB);  
        do
        {
            // curVIB->addrStart.HI16 = 0;
            // curVIB->addrStart.LO16 = 0;
            // curVIB->varBlkNum = 0;
            // curVIB->varCRC = 0;
            ////SCYHF
            // (*((UINT32 *)(curVIB+16)))=0;//addrStart
            // (*((UINT32 *)(curVIB+20)))=0;//varBlkNum AND varCRC
            curVIB->addrStart=0;//addrStart
            curVIB->varBlkNum=0;//varBlkNum
            curVIB->varCRC = 0;//varCRC
            ////SCYHF
            curVIB->fromTVCB = (VOID *)curTVCB;
            curVIB ++;
        } while (curVIB < curTVCB);
        curTVCB = (TVCB *)((UINT32)curTVCB + g_TVCBSize);
    }
    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_pcramboxInit
 Description : Initialize Static Memory pool
 Input       : pBoxMem    --- Pointer to the memory pool
               uwBoxSize  --- Size of the memory pool
 Output      : None
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_pcramboxInit(VOID *pBoxMem, UINT32 uwBoxSize)
{
    VOID *pstNode = NULL;
    UINT16 i;
    UINTPTR uvIntSave;
    UINT32 uwRet = LOS_NOK;
    //
    UINT8 TempData[4];
    UINT32 PCRAM_32Bit;

    g_TVBHead = (VOID *)((UINT32)pBoxMem + pcrambox_magicsize);

    g_TVCBNum = 20;
    g_VIBSize = sizeof(VIB);

    g_TVCBSize = sizeof(TVCB) + g_VIBSize * 20;
    // if(*((UINT16 *)pBoxMem) == OS_pcrambox_MAGIC)
    EXMC_PCRAM_BufferRead(TempData,pBoxMem,4);
    PCRAM_32Bit=(*((UINT32 *)pBoxMem));
    if(PCRAM_32Bit== OS_pcrambox_MAGIC)
    {
        return LOS_OK;
    }
    uwBoxSize -= (2 * g_TVCBSize * g_TVCBNum + pcrambox_magicsize);
    if (pBoxMem == NULL ||  uwBoxSize < sizeof(LOS_MEM_POOL_INFO))
    {
        return LOS_NOK;
    }

    //uvIntSave = LOS_IntLock();
    /*
     * The node size is aligned to the next 4 boundary.
     * Memory that is not enough for one node size in the memory pool will be ignored.
     */
    uwRet = osIndexInit(g_TVBHead);
    if(uwRet != LOS_OK)
    {
       // LOS_IntRestore(uvIntSave);
       
        return LOS_NOK;
    }
    else
    {
        uwRet = osIndexInit((VOID *)((UINT32)g_TVBHead + g_TVCBNum * g_TVCBSize));        /* SCLIST2 INIT */
    }
    
    /*
     * calc the length of the index area
     * SKIP the index area(SClist1 & SCLIST2)
     * The PCRAM pool is divided into two parts, INDEX area as well as FREE MEMORY NODE area
     */
    pstNode = (VOID *)((UINT32)pBoxMem + (UINT32)(2 * g_TVCBNum * g_TVCBSize) + pcrambox_magicsize);

    uwRet = OS_MemInit((VOID *)(BOXMEM_ALIGN(pstNode,OS_BOXMEM_BASE_ALIGN)), BOXMEM_ALIGN(uwBoxSize - OS_BOXMEM_BASE_ALIGN, OS_BOXMEM_BASE_ALIGN));
    if(uwRet != LOS_OK)
    {
        return LOS_NOK;
    }
    OS_pcrambox_SET_MAGIC(pBoxMem);
    return LOS_OK;
}

/*****************************************************************************
 Function : SC_MALLOC
 Description : Allocate sc block from pcram Memory pool
 Input       : pBoxMem  --- Pointer to memory pool
 Output      : None
 Return      : Pointer to allocated memory block
*****************************************************************************/
LITE_OS_SEC_TEXT VOID *SC_MALLOC(UINT8 Identifier[], UINT32 Length, UINT8 *Flag)
{
    // UINT8 TID;
    ////SCYHF
    UINT32 TID;
    ////SCYHF
    UINT32 uwRet = LOS_NOK;
    UINTPTR uvIntSave;
    VOID *pRet;
    //uvIntSave = LOS_IntLock();

    // TID = (UINT8)LOS_CurTaskIDGet();
    ////SCYHF
    TID = (UINT32)LOS_CurTaskIDGet();
    ////SCYHF
    if(TID == LOS_ERRNO_TSK_ID_INVALID)
    {
        //LOS_IntRestore(uvIntSave);
        return NULL;
    }
    printf("TID:%d    Name:%s    want MALLOC\r\n", TID, Identifier);
    pRet = osFoundVIB(TID, Identifier);
    
    if(pRet != NULL)
    {
        ///SCYHF QUESTION
        uwRet = osCheckCRC(pRet);
        if(uwRet != LOS_OK)
        {
            osRecoverSClist((VIB *)pRet);
        }
        if(*Flag == 0)
        {
            // LOS_pcramboxClr(OS_PCRAM_START_ADDR , (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart)), Length);
            ////SCYHF
            LOS_pcramboxClr(OS_PCRAM_START_ADDR , (VOID *)(((VIB *)pRet)->addrStart), Length);
            ////SCYHF
            *Flag = 1;
            //LOS_IntRestore(uvIntSave);

            // return (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart));
            ////SCYHF
            return (VOID *)(((VIB *)pRet)->addrStart);
            ////SCYHF
        }
        else
        {
            // return (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart));
            ////SCYHF
            return (VOID *)(((VIB *)pRet)->addrStart);
            ////SCYHF
        }
        
    }
    else
    {
        pRet = OS_MemAlloc(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), Length);
        if(pRet != NULL)
        {
            printf("%s alloc success!!\r\n", Identifier);
            uwRet = osCreateVIB(pRet, TID, Identifier, Length);
            LOS_pcramboxClr(OS_PCRAM_START_ADDR , pRet, Length);
            *Flag = 0;
            //LOS_IntRestore(uvIntSave);
            
            return pRet;
        } 
        else
        {
            printf("alloc failed!!\r\n");
            //LOS_IntRestore(uvIntSave);
            return NULL;
        }
        
    }
}

/*****************************************************************************
 Function : SC_FREE
 Description : Allocate sc block from pcram Memory pool
 Input       : pBoxMem  --- Pointer to memory pool
 Output      : None
 Return      : Pointer to allocated memory block
*****************************************************************************/
LITE_OS_SEC_TEXT UINT32 SC_FREE(UINT8 Identifier[])
{
    // UINT8 TID;
    ////SCYHF
    UINT32 TID;
    ////SCYHF
    UINT32 uwRet = LOS_NOK;
    UINT16 BlkNum, uwBlkSize;
    UINTPTR uvIntSave;
    VOID *pRet;
    uvIntSave = LOS_IntLock();
    // TID = LOS_CurTaskIDGet();
    ////SCYHF
    TID = (UINT32)LOS_CurTaskIDGet();
    ////SCYHF
    if(TID == LOS_ERRNO_TSK_ID_INVALID)
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    pRet = osFoundVIB(TID, Identifier);
    if(pRet == NULL)
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    // uwRet =OS_MemFree(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), (VOID *)(OS_ADDR16to32(((VIB *)pRet)->addrStart)));
    ////SCYHF
    uwRet =OS_MemFree(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), (VOID *)(((VIB *)pRet)->addrStart));
    ////SCYHF
    if(uwRet == LOS_OK)
    {
        uwRet = osDeleteVIB(pRet);
    }
    else
    {
        (VOID)LOS_IntRestore(uvIntSave);
        return LOS_NOK;
    }
    (VOID)LOS_IntRestore(uvIntSave);
    return uwRet;
}

/*****************************************************************************
 Function : LOS_pcramboxClr
 Description : Clear the memory block
 Input       : pBoxMem  --- Pointer to memory pool
               pBox     --- Pointer to memory block to clear
               BlkNum   --- the number of the block need to clear
 Output      : None
 Return      : None
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID LOS_pcramboxClr(VOID *pBoxMem, VOID *pBox, UINT32 Length)
{
    if (pBoxMem == NULL || pBox == NULL)
    {
        return;
    }

    // memset(pBox, 0, Length);
    exmc_pcram_clear(pBox,Length);
}

/*****************************************************************************
 Function : LOS_pcramboxStatisticsGet
 Description : Get information about pcrambox
 Input       : pBoxMem     --- Pointer to the calculate pcrambox
 Output      : puwMaxBlk   --- Record the total number of pcrambox
               puwBlkCnt   --- Record the number of the allocated blocks of pcrambox
               puwBlkSize  --- Record the block size of pcrambox
 Return      : LOS_OK - OK, LOS_NOK - Error
*****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_pcramboxStatisticsGet(VOID *pBoxMem, LOS_MEM_STATUS *pstStatus)
{
    OS_MemStatisticsGet(BOXMEM_ALIGN(pcram_mempool_addr(OS_PCRAM_START_ADDR),OS_BOXMEM_BASE_ALIGN), pstStatus);
    return LOS_OK;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
